﻿/*
 * Copyright (c) 2009, Thiago M. Sayao <thiago.sayao@gmail.com>
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 *  * Redistributions of source code must retain the above copyright notice, 
 *    this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *  * Neither the name of the author nor the names of its contributors may be 
 *    used to endorse or promote products derived from this software without 
 *    specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 * POSSIBILITY OF SUCH DAMAGE.
 */

using System;
using System.Collections.Generic;
using System.Web.Mvc;
using System.Web.Routing;
using System.Xml;
using System.ServiceModel.Syndication;
using System.IO;
using DotNetBurner.Model;
using DotNetBurner.Core;
using DotNetBurner.Web.Settings;
using Resources;

namespace DotNetBurner
{
    public enum FeedType
    {
        RSS20,
        ATOM10
    }

    public static class FeedHelper
    {
        public static void GenerateFeed(IEnumerable<Story> stories, 
                                        IEnumerable<Category> categories, 
                                        Stream output, 
                                        FeedType type,
                                        UrlHelper urlHelper)
        {

            // Create an XmlWriter to write the feed into it
            using (XmlWriter writer = XmlWriter.Create(output))
            {
                // Set the feed properties
                SyndicationFeed feed = new SyndicationFeed
                    (SiteSettings.Settings.Name,
                     SiteSettings.Settings.Title,
                     new Uri(SiteSettings.Settings.Address));

                feed.LastUpdatedTime = DateTime.UtcNow;
                feed.Language = SiteSettings.Settings.Language;

                feed.Authors.Add(new SyndicationPerson(SiteSettings.Settings.AdminMail,
                                                       SiteSettings.Settings.Name,
                                                       SiteSettings.Settings.Address));

                // Add categories
                foreach (var category in categories)
                    foreach(var subcat in category.SubCategories)
                        feed.Categories.Add(new SyndicationCategory(subcat.Name));

                // Set generator
                feed.Generator = SiteSettings.Settings.Title;

                // Set language
                feed.Language = SiteSettings.Settings.Language;
                string siteUrl = SiteSettings.Settings.Address;


                // Add post items
                List<SyndicationItem> items = new List<SyndicationItem>();

                foreach (var story in stories)
                {
                    string url = String.Concat(siteUrl,
                                               urlHelper.RouteUrl("Detail",
                                                                  new RouteValueDictionary
                                                                      {
                                                                          {"id", story.StoryId},
                                                                          {"title", story.Title.ConvertToUrlPath()}
                                                                      }));

                    string voteButton = "{0}<br />".FormatWith(SwissKnife.GetVoteButtonFor(story.Url));
                    string readMore = "<a href=\"{0}\" title=\"{1}\">{1}</a>".FormatWith(url, Strings.More);
                    string description = String.Concat(story.Description, "&nbsp;", readMore);

                    TextSyndicationContent content =
                        SyndicationContent.CreateHtmlContent(String.Concat("<div><p>", description, "</p>",
                                                                           voteButton, "</div>"));

                    SyndicationItem item = new SyndicationItem(story.Title,
                                                               content,
                                                               new Uri(story.Url),
                                                               story.Url,
                                                               new DateTimeOffset(story.PostedOn));
                    item.PublishDate = story.PostedOn;
                    item.Categories.Add(new SyndicationCategory(story.CategoryName));

                    items.Add(item);
                }

                feed.Items = items;

                // Write the feed to output
                if (type == FeedType.RSS20)
                {
                    Rss20FeedFormatter rssFormatter = new Rss20FeedFormatter(feed);
                    rssFormatter.WriteTo(writer);
                }
                else
                {
                    Atom10FeedFormatter atomFormatter = new Atom10FeedFormatter(feed);
                    atomFormatter.WriteTo(writer);
                }

                writer.Flush();
            }
        }
    }
}
